; ------------------------------------
; EU-Rent
; Matus Tejiscak <ziman@functor.sk>
; Reasoning with computer support 2011
; ------------------------------------
;
; Purpose: Based on historical records, this system will decide whether
; a customer is eligible to rent a car.
;

; -- Templates --
(deftemplate event
  (slot id)
  (slot event-date)
  (slot customer-name)
  (slot car-model)
  (slot branch)
)

(deftemplate customer
  (slot name)
  (slot blacklisted)
  (slot late-returns)
)

(deftemplate pre-reservation extends event
  (slot start-date)
  (slot days)
  (slot car-group (default A))
  (slot credit-card)
)

(deftemplate reservation extends pre-reservation)

(deftemplate rental extends event
  (slot reservation (default no))
  (slot return-schedule)
)

(deftemplate late-return extends event)
(deftemplate proper-return extends event
  (slot early (default no))
)

(deftemplate retback extends event)

(deftemplate can-rent extends pre-reservation)

; -- Rules --
(defrule blacklist-reservations
  "delete reservations from blacklisted customers"
  (customer (name ?cust) (blacklisted yes))
  ?r <- (reservation (customer-name ?cust))
  =>
  (retract ?r)
  (printout t "... " ?cust " is blacklisted! Deleting reservation!" crlf))

(defrule reservations-to-rentals
  "assign reservations to rentals"
  ?rental <- (rental (event-date ?date) (customer-name ?cust) (reservation no))
  ?reserv <- (reservation (start-date ?date) (days ?days) (customer-name ?cust))
  =>
  (modify ?rental (reservation yes) (return-schedule (+ ?date ?days)))
  (retract ?reserv)
  (printout t "... The rental " ?rental " has been connected with the reservation " ?reserv "." crlf)
)

(defrule ccard-charge
  "charge credit card and cancel reservation"
  ?r <- (reservation (customer-name ?cust) (credit-card yes))
  =>
  (retract ?r)
  (printout t "--> Charge " ?cust "'s credit card for 1 day's rent. Reservation cancelled." crlf)
)

(defrule retbacks-on-time
  ?retback <- (retback (customer-name ?cust) (event-date ?date))
  ?rental <- (rental (customer-name ?cust)
    (return-schedule ?sched &: (neq ?sched nil) &: (eq ?sched ?date)))
  =>
  (retract ?retback ?rental)
  (assert (proper-return (customer-name ?cust) (event-date ?date)))
  (printout t "... Car returned by " ?cust " on time." crlf)
)

(defrule retbacks-early
  ?retback <- (retback (customer-name ?cust) (event-date ?date))
  ?rental <- (rental (customer-name ?cust)
    (return-schedule ?sched &: (neq ?sched nil) &: (< ?date ?sched)))
  =>
  (retract ?retback ?rental)
  (assert (proper-return (customer-name ?cust) (event-date ?date) (early yes)))
  (printout t "... Car returned by " ?cust " early." crlf)
)

(defrule retbacks-late
  ?retback <- (retback (customer-name ?cust) (event-date ?date))
  ?rental <- (rental (customer-name ?cust)
    (return-schedule ?sched &: (neq ?sched nil) &: (> ?date ?sched)))
  =>
  (retract ?retback ?rental)
  (assert (late-return (customer-name ?cust) (event-date ?date)))
  (printout t "... Car returned by " ?cust " late. Event recorded." crlf)
)

(defrule can-rent-blacklist
  ?r <- (can-rent (customer-name ?cust) (id ?id))
  (customer (name ?cust) (blacklisted yes))
  =>
  (retract ?r)
  (printout t "??? (" ?id ") No, " ?cust " is blacklisted and cannot rent cars at all." crlf)
)

(defrule can-rent-multiple
  ?r <- (can-rent (customer-name ?cust) (start-date ?start) (days ?days) (id ?id))
  (rental (customer-name ?cust) (event-date ?rstart &: (<= ?rstart ?start)))
  =>
  (retract ?r)
  (printout t "??? (" ?id ") No, " ?cust " cannot rent multiple cars simultaneously." crlf)
)

(defrule can-rent-positive
  ?r <- (can-rent (customer-name ?cust) (id ?id))
  =>
  (retract ?r)
  (printout t "??? (" ?id ") Yes, " ?cust " can rent the car." crlf)
)

; -- Fact set 1 --
(deffacts history
  (customer (name "John Doe") (blacklisted yes))
  (reservation (start-date 10) (days 5) (customer-name "John Doe"))
  (reservation (start-date 10) (days 5) (customer-name "Mary Lambs"))
  (reservation (start-date 11) (days 5) (customer-name "Godot") (credit-card yes))
  (can-rent (id 1) (customer-name "John Doe") (start-date 12) (days 5))
  (rental   (event-date 10)        (customer-name "Mary Lambs"))
  (can-rent (event-date 11) (id 2) (customer-name "Mary Lambs") (start-date 11))
  (can-rent (event-date 12) (id 3) (customer-name "Mary Lambs") (start-date 14))
  (retback  (event-date 13)        (customer-name "Mary Lambs"))
  (can-rent (event-date 14) (id 4) (customer-name "Mary Lambs") (start-date 14))
)

(reset)
(printout t crlf "===== Running the inference engine =====" crlf crlf)
(run)
(printout t crlf "===== Dumping the final facts =====" crlf crlf)
(facts)
